import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_2d_amap/flutter_2d_amap.dart';
import 'package:flutterlib/common/aliyun/aliyun_oss.dart';
import 'package:flutterlib/common/aliyun/oss_client.dart';
import 'package:flutterlib/common/constants/constants.dart';
import 'package:flutterlib/common/net/retrofit/activity_api.dart';
import 'package:flutterlib/common/net/retrofit/user_api.dart';
import 'package:flutterlib/common/style/font_awesome4_icons.dart';
import 'package:flutterlib/common/utils/color_utils.dart';
import 'package:flutterlib/common/utils/utils.dart';
import 'package:flutterlib/model/activity/activity_create_request.dart';
import 'package:flutterlib/widgets/editor/editor_view.dart';
import 'package:flutterlib/widgets/editor/image_picker.dart';
import 'package:geolocator/geolocator.dart';
import 'package:rounded_loading_button/rounded_loading_button.dart';
import 'package:thrio/thrio.dart';
import 'package:path/path.dart' as path;

const String STATIC_STRING_CREATE_ACTIVITY = "发布活动";
const String STATIC_STRING_CREATE_DEPLOY_ACTIVITY = "发布招募活动";
const String STATIC_STRING_UPLOAD_LOGO = "上传封面";
const String STATIC_STRING_TITLE = "标题";
const String STATIC_STRING_TITLE_HINT = "比如：找小伙伴结伴一起学日语";
const String STATIC_STRING_ADDRESS = "地点";
const String STATIC_STRING_OFFLINE = "线下";
const String STATIC_STRING_ONLINE = "线上";
const String STATIC_STRING_ADDRESS_AREA = "所在地区";
const String STATIC_STRING_ADDRESS_DETAIL = "详细地址";
const String STATIC_STRING_TIME = "时间";
const String STATIC_STRING_TIME_TO = "至";
const String STATIC_STRING_TYPE = "形式";
const String STATIC_STRING_PERSON_NUMBER = "人数";
const String STATIC_STRING_PRICE = "费用";
const String STATIC_STRING_FILL_DESCRIPATION = "填写详情";
const String STATIC_STRING_QUESTION = "问题";
const String STATIC_STRING_QUESTION_HINT = "陌生人加入招募活动需要先回答招募者提出的问题。通过者方才可成功加入。";
const String STATIC_STRING_AGREEMENT = "同意活动协议";
const String STATIC_STRING_PLEASE_SELECT = "请选择";
const String STATIC_STRING_PLEASE_SELECT_FLAG = ">";
const String STATIC_STRING_CONFIRM_CREATE = "确定发布";

//兴趣活动
abstract class BaseActivityCreatePage extends StatefulWidget {
  const BaseActivityCreatePage({Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState();
}

abstract class BaseActivityCreatePageState<T extends BaseActivityCreatePage>
    extends State<T> {
  File image;
  String logoRemote = '';
  bool isAgree = false;

  DateTime startTime;
  DateTime endTime;
  OSSClient client;

  final SettingsStore store =
      Provider.of<SettingsStore>(currentContext, listen: false);
  TextEditingController titleController = TextEditingController();
  TextEditingController personNumberController = TextEditingController();
  EditorViewController editorController = EditorViewController();
  final LoadingDialogController loadingDialogController =
      LoadingDialogController();
  int uploadedAssets = 0;

  final FocusNode titleFocusNode = FocusNode();
  final FocusNode personCountfocusNode = FocusNode();
  final FocusNode descFocusNode = FocusNode();

  final Map<File, String> uploadedAssetId = <File, String>{};

  int get imagesLength => editorController.files.length;

  bool get hasImages => editorController.files.isNotEmpty;

  String get filteredContent => editorController.content?.trim();

  bool get isContentNotEmpty => filteredContent?.isNotEmpty ?? false;

  final RoundedLoadingButtonController btnController =
      new RoundedLoadingButtonController();

  final OSSAuthCredentialProvider _provider = OSSAuthCredentialProvider.init(
    authServerUrl: 'https://xx/getStsToken',
    fetcher: (authServerUrl) async {
      return UserApi.builder().ossToken();
    },
  );

  final List<CancelToken> assetsUploadCancelTokens = <CancelToken>[];

  String get dateTimeFormat {
    if (startTime == null || endTime == null) {
      return '';
    }
    return DateUtil.formatDate(startTime, format: DateFormats.y_mo_d) +
        '-' +
        DateUtil.formatDate(endTime, format: DateFormats.y_mo_d);
  }

  String get activityTitle => STATIC_STRING_CREATE_ACTIVITY;

  @override
  void initState() {
    super.initState();
    client = OSSClient(
      endpoint: 'oss-cn-hangzhou.aliyuncs.com',
      credentialProvider: _provider,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: HexColor("#ECECEC"),
      appBar: AppBar(
        title: Text(
          activityTitle,
          style: TextStyle(color: Colors.black),
        ),
        backgroundColor: HexColor("#ECECEC"),
        leading: MyBackButton(),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            uploadCover(),
            fillIntro(),
          ],
        ),
      ),
    );
  }

  Widget uploadCover() {
    return Stack(
      alignment: Alignment.center,
      children: [
        InkWell(
          onTap: () {
            if (image == null) {
              return;
            }
            addImage(
                context,
                (file) => setState(() {
                      image = file;
                      unFocusTextField();
                    }));
          },
          child: AspectRatio(
              aspectRatio: 375 / 230,
              child: Container(
                  child: image == null
                      ? Container(color: HexColor("#D1D1D1"))
                      : Image.file(
                          image,
                          fit: BoxFit.cover,
                        ))),
        ),
        FractionallySizedBox(
            widthFactor: 156 / 375,
            child: image != null
                ? Container()
                : RaisedButton(
                    color: HexColor("#333333"),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(16)),
                    onPressed: () {
                      addImage(
                          context,
                          (file) => setState(() {
                                image = file;
                                unFocusTextField();
                              }));
                    },
                    child: Text(
                      STATIC_STRING_UPLOAD_LOGO,
                      style: TextStyle(color: Colors.white, fontSize: 15),
                    ))),
      ],
    );
  }

  Widget fillIntro();

  Widget getSelectWidget(content, VoidCallback onPressed) {
    return Column(
      children: [
        GestureDetector(
          behavior: HitTestBehavior.opaque,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                content.isEmpty ? STATIC_STRING_PLEASE_SELECT : content,
                style: TextStyle(color: Colors.grey, fontSize: 16),
              ),
              const Icon(Icons.keyboard_arrow_right, color: Colors.grey),
            ],
          ),
          onTap: onPressed,
        ),
        Padding(
            padding: EdgeInsets.only(top: 8),
            child: Divider(
              height: 1,
            )),
      ],
    );
  }

  void unFocusTextField();

  String getImageTag(String value, {bool withTag: true}) => withTag
      ? "<img src='https://quhui123.oss-cn-hangzhou.aliyuncs.com/${value}'></img>"
      : 'https://quhui123.oss-cn-hangzhou.aliyuncs.com/${value}';

  Future<void> checkConvention() async {
    if (image == null) {
      stopSend("为了更好展示,请先选择封面");
      return;
    }
    if (titleController.text.isEmpty) {
      stopSend("标题不能为空");
      return;
    }
    if (editorController.content.isEmpty) {
      stopSend("描述不能为空");
      return;
    }
    if (!isAgree) {
      stopSend("请先同意注意事项");
      return;
    }
    if (startTime == null || endTime == null) {
      stopSend("请先选择开始和结束时间");
      return;
    }


    final bool confirm = await ConventionDialog.show(context);
    if (confirm) {
      LoadingDialog.show(
        context,
        controller: loadingDialogController,
        text: (image != null || hasImages) ? '正在上传图片' : '正在发布...',
      );
      runLogoUploadRequests();
    }
  }

  void stopSend(msg) {
    ToastUtils.toast(msg);
    btnController.stop();
  }

  Future<void> runPublishRequest() async {
    try {
      var content = filteredContent;

      uploadedAssetId.forEach((key, value) {
        content += getImageTag(value);
      });

      // trueDebugPrint("flutterting create post success" + jsonEncode(bean));
      ActivityCreateRequest createRequest = getCreateRequestBean(content);
      var activityDetailBean =
          await ActivityApi.builder().create(createRequest);

      trueDebugPrint("flutterting create activity success" +
          jsonEncode(createRequest.toJson()));
      trueDebugPrint("flutterting create activity success" +
          activityDetailBean.toString());
      if (activityDetailBean != null) {
        loadingDialogController.changeState('success', '发布成功',
            duration: 2.seconds, customPop: () {
          Navigator.pop(context);
          NavigatorUtils.ThrioNavigatorPop();
        });
      }
      btnController.reset();
    } catch (e, stack) {
      trueDebugPrint("flutterting create activity error" + stack.toString());
      loadingDialogController.changeState('failed', '发布失败');
      btnController.reset();
    } finally {
      if (mounted) {
        setState(() {});
      }
    }
  }

  ActivityCreateRequest getCreateRequestBean(String content);

  void runImagesRequests() {
    editorController.files.forEach(assetsUploadRequest);
  }

  Future<void> assetsUploadRequest(File asset) async {
    final CancelToken cancelToken = CancelToken();
    assetsUploadCancelTokens.add(cancelToken);

    final bytes = await asset.readAsBytes();
    trueDebugPrint("flutterting upload image" + bytes.length.toString());

    try {
      var result = await client.postObject(
          bytes,
          'quhui123',
          "activity/" +
              DateUtil.getNowDateMs().toString() +
              path.basename(asset.path));
      if (result is OSSResponse) {
        trueDebugPrint("flutterting upload image" + result.toString());
        uploadedAssetId[asset] = result.fileKey.toString();
        ++uploadedAssets;
        loadingDialogController.updateText(
          '正在上传图片'
          '(${math.min(uploadedAssets + 1, imagesLength)}/$imagesLength)',
        );

        /// Execute publish when all assets were upload.
        /// 所有图片上传完成时进行发布
        if (uploadedAssets == imagesLength) {
          unawaited(runPublishRequest());
        }
      } else {
        throw Error.safeToString('Asset ${asset.path} upload failed');
      }
    } catch (e, stack) {
      trueDebugPrint("flutterting upload image error" + stack.toString());
      uploadedAssets = 0; // 上传清零
      loadingDialogController.changeState('failed', '图片上传失败');
      btnController.error();

      /// 取消所有的上传请求并清空所有cancel token
      assetsUploadCancelTokens
        ..forEach((CancelToken token) => token?.cancel())
        ..clear();

      if (mounted) {
        setState(() {});
      }

      trueDebugPrint('Error when trying upload images: $e');
      if (e is DioError) {
        trueDebugPrint('${e.response}');
      }
      trueDebugPrint('Images requests will be all cancelled.');
    }
  }

  void runLogoUploadRequests() async {
    final CancelToken cancelToken = CancelToken();

    final bytes = await image.readAsBytes();
    trueDebugPrint("flutterting upload logo" + bytes.length.toString());

    try {
      var result = await client.postObject(
          bytes,
          'quhui123',
          "activity/" +
              DateUtil.getNowDateMs().toString() +
              path.basename(image.path));
      if (result is OSSResponse) {
        trueDebugPrint("flutterting upload image" + result.toString());
        logoRemote = getImageTag(result.fileKey.toString(), withTag: false);
        loadingDialogController.updateText(
          'logo上传成功',
        );
        if (hasImages) {
          runImagesRequests();
        } else {
          unawaited(runPublishRequest());
        }
      } else {
        throw Error.safeToString('Asset ${image.path} upload failed');
      }
    } catch (e, stack) {
      trueDebugPrint("flutterting upload image error" + stack.toString());
      loadingDialogController.changeState('failed', 'logo上传失败');
      btnController.error();

      /// 取消所有的上传请求并清空所有cancel token
      cancelToken?.cancel();
      if (mounted) {
        setState(() {});
      }

      trueDebugPrint('Error when trying upload images: $e');
      if (e is DioError) {
        trueDebugPrint('${e.response}');
      }
      trueDebugPrint('Images requests will be all cancelled.');
    }
  }
}
